﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ReLogic.Content;
using System;
using Terraria;
using Terraria.GameContent;
using Terraria.ID;
using Terraria.UI;
using WorseGame.Common.Cores.Custom.Enums;
using WorseGame.Common.Cores.Custom.Structs;

namespace WorseGame.Common.UIs.Elements
{

    public class FishIcon : UIElement
    {

        public bool shouldShake;

        private FishMovementType _fishMovementType;

        private int _fishDifficulty;

        private float _targetPosition = -1f;

        private float _fishVelocity;

        private float _fishAcceleration;

        private float _floaterSinkerAcceleration;

        private readonly Asset<Texture2D> _fishSprite;

        private readonly float _stardewMaxZoneHeight = 548f;
        private readonly float _iconScale = 0.6f;

        public FishIcon(CatchData catchData)
        {
            _fishMovementType = catchData.movementType;
            _fishDifficulty = catchData.fishDifficulty;

            Main.instance.LoadItem(ItemID.Bass);
            _fishSprite = TextureAssets.Item[ItemID.Bass];
            Width.Set(_fishSprite.Value.Width * _iconScale, 0f);
            Height.Set(_fishSprite.Value.Height * _iconScale, 0f);
            Left.Set(5f, 0f);
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            float position = VAlign;

            if (Main.rand.NextFloat() < _fishDifficulty * (float)(_fishMovementType != FishMovementType.Smooth ? 1 : 20) / 4000f && (_fishMovementType != FishMovementType.Smooth || _targetPosition == -1f))
            {
                _targetPosition = position + Main.rand.NextFloat(-position, 1f - position) * Math.Min(99f, _fishDifficulty + Main.rand.NextFloat(10f, 45f)) / 100f;
            }

            _floaterSinkerAcceleration = _fishMovementType switch
            {
                FishMovementType.Floater => Math.Max(_floaterSinkerAcceleration - 0.01f / _stardewMaxZoneHeight, -1.5f / _stardewMaxZoneHeight),
                FishMovementType.Sinker => Math.Min(_floaterSinkerAcceleration + 0.01f / _stardewMaxZoneHeight, 1.5f / _stardewMaxZoneHeight),
                _ => _floaterSinkerAcceleration
            };

            if (Math.Abs(position - _targetPosition) >= 3f / _stardewMaxZoneHeight && _targetPosition != -1f)
            {
                _fishAcceleration = (_targetPosition - position) / (Main.rand.NextFloat(10f, 30f) + (100f - Math.Min(100f, _fishDifficulty)));
                _fishVelocity += (_fishAcceleration - _fishVelocity) / 5f;
            }

            else if (_fishMovementType != FishMovementType.Smooth && Main.rand.NextFloat() < _fishDifficulty / 2000f)
            {
                _targetPosition = position + (Main.rand.NextBool()
                    ? Main.rand.NextFloat(-100f / _stardewMaxZoneHeight, -51f / _stardewMaxZoneHeight)
                    : Main.rand.NextFloat(50f / _stardewMaxZoneHeight, 101f / _stardewMaxZoneHeight));
            }

            else
            {
                _targetPosition = -1f;
            }

            if (_fishMovementType == FishMovementType.Dart && Main.rand.NextFloat() < _fishDifficulty / 1000f)
            {
                _targetPosition = position + (Main.rand.NextBool()
                    ? Main.rand.NextFloat((-100f - _fishDifficulty * 2f) / _stardewMaxZoneHeight, -51f / _stardewMaxZoneHeight)
                    : Main.rand.NextFloat(50f / _stardewMaxZoneHeight, (101f + _fishDifficulty * 2f) / _stardewMaxZoneHeight));
            }

            _targetPosition = Math.Max(-1f, Math.Min(_targetPosition, 1f));
            position += _fishVelocity + _floaterSinkerAcceleration;

            position = MathHelper.Clamp(position, 0f, 1f);

            VAlign = position;
        }

        protected override void DrawSelf(SpriteBatch spriteBatch)
        {

            Vector2 shakeDisplacement = shouldShake
                ? new Vector2(0.5f * Main.rand.NextBool().ToDirectionInt(), 0.5f * Main.rand.NextBool().ToDirectionInt())
                : Vector2.Zero;
            spriteBatch.Draw(
                _fishSprite.Value,
                GetDimensions().Position() + shakeDisplacement,
                null,
                Color.White,
                0f,
                Vector2.Zero,
                _iconScale,
                SpriteEffects.None,
                0f
            );
        }

        public void ResetElement(CatchData newCatchData)
        {
            VAlign = 0.95f;

            _fishDifficulty = newCatchData.fishDifficulty;
            _fishMovementType = newCatchData.movementType;
            _targetPosition = -1f;
            _fishVelocity = _fishAcceleration = _floaterSinkerAcceleration = 0f;
        }
    }
}